/**
 * 协程工具
 * nodejs大多是单线程，但是使用协程可以减少重负载时候的卡顿
 */
class CoroutineTool {
    private static MaxFPS = 60;
    private static isRunning: boolean = false;
    private static gList: Array<Generator> = new Array<Generator>();
    /**
     * 启动协程执行
     * @param g 生成器
     */
    static Start(g: Generator) {
        var index = this.gList.indexOf(g);
        if (index < 0) {
            this.gList.unshift(g);
            if (!this.isRunning) {
                this.isRunning = true;
                this.Run();
            }
        }
    }
    /**
     * 停止协程执行
     * @param g 生成器
     */
    static Stop(g: Generator) {
        var index = this.gList.indexOf(g);
        if (index > -1) {
            this.gList.splice(index, 1);
        }
    }
    private static Run() {
        if (this.gList.length == 0) {
            this.isRunning = false;
            return;
        }
        this.RunGenerator(1000 / this.MaxFPS);
        setTimeout(() => this.Run(), 0);
    }
    private static RunGenerator(minTime: number) {
        let begin = +new Date();
        while (true) {
            if (this.gList.length == 0)
                return;
            let g = this.gList.pop();
            try {
                let r = g!.next();
                if (!r.done)
                    this.gList.unshift(g!);
            }
            catch (e) {
                console.error(e);
            }
            let end = +new Date();
            if (end - begin >= minTime)
                return;
        }
    }
}

class CoroutineToolTest {
    private async_oldTask: boolean = false;
    private asyncHandler!: Generator;
    aHeavyTask_coroutine() {
        if (this.async_oldTask) {
            CoroutineTool.Stop(this.asyncHandler);
            this.async_oldTask = false;
            console.log("停止前面的");
        }
        this.asyncHandler = this.aHeavyTask(100, (e) => {
            console.log([`处理${e}`]);
        });
        CoroutineTool.Start(this.asyncHandler);
        this.async_oldTask = true;
    }
    private * aHeavyTask(
        n: number,
        cb: (nowNumber: number) => void): Generator<unknown, any, unknown> {

        for (let i = 0; i < n; i++) {
            
            cb(i);
            yield i;
        }

    }

    userAction(){
        for (let i = 0; i < 100; i++) {
            console.log(`          用户动作 ${i}`);
        }
        
    }

}

let ctt = new CoroutineToolTest();
ctt.aHeavyTask_coroutine();
ctt.aHeavyTask_coroutine();
ctt.aHeavyTask_coroutine();
ctt.aHeavyTask_coroutine();
ctt.userAction();
/**
 * aHeavyTask_coroutine在执行时候不影响userAction的执行
 */